package com.newlink.building.common_base.utils;

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;

import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Create on 2022/2/24
 *
 * @author jake
 * @desc thread manager
 */
public class ThreadUtils {

    private final Executor mDiskIO;

    private final Executor mNetworkIO;

    private final MainThreadExecutor mMainThread;
    private final ScheduledThreadPoolExecutor schedule;

    private static ThreadUtils instance;

    private static final Object object = new Object();

    public static ThreadUtils getInstance() {
        if (instance == null) {
            synchronized (object) {
                if (instance == null) {
                    instance = new ThreadUtils();
                }
            }
        }
        return instance;
    }

    private ThreadUtils() {
        this.mDiskIO = new ThreadPoolExecutor(
                1,
                1,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(),
                new MyThreadFactory("single"));
        this.mMainThread = new MainThreadExecutor();
        this.mNetworkIO = new ThreadPoolExecutor(
                3,
                3,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(),
                new MyThreadFactory("fixed"));
        this.schedule = new ScheduledThreadPoolExecutor(5, new MyThreadFactory("sc"), new ThreadPoolExecutor.AbortPolicy());
    }

    public Executor diskIo() {
        return mDiskIO;
    }

    public ScheduledThreadPoolExecutor schedule() {
        return schedule;
    }

    public Executor networkIo() {
        return mNetworkIO;
    }

    public MainThreadExecutor mainThread() {
        return mMainThread;
    }

    public static class MainThreadExecutor implements Executor {
        private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());

        @Override
        public void execute(@NonNull Runnable command) {
            mainThreadHandler.post(command);
        }

        public void executeDelayed(@NonNull Runnable command, long delay) {
            mainThreadHandler.postDelayed(command, delay);
        }
    }

    static class MyThreadFactory implements ThreadFactory {

        private final String name;
        private int count = 0;

        MyThreadFactory(String name) {
            this.name = name;
        }

        @Override
        public Thread newThread(@NonNull Runnable r) {
            count++;
            return new Thread(r, name + "-" + count + "-Thread");
        }
    }

}